﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace PlayDeezGames.Common
{
    public abstract class MessageHandlerBase
    {
        private MessageHandlerBase() { }
        private MessageHandlerBase parent = null;
        private List<MessageHandlerBase> children = new List<MessageHandlerBase>();
        private void AddChild(MessageHandlerBase theChild)
        {
            if (theChild == null) return;
            RemoveChild(theChild);
            Children.Add(theChild);
        }
        private void RemoveChild(MessageHandlerBase theChild)
        {
            if (theChild == null) return;
            Children.Remove(theChild);
        }
        protected List<MessageHandlerBase> Children
        {
            get
            {
                return children;
            }
        }
        public MessageHandlerBase(MessageHandlerBase theParent)
        {
            Parent = theParent;
        }
        public MessageHandlerBase Parent
        {
            get
            {
                return parent;
            }
            set
            {
                MessageHandlerBase testParent = value;
                while (testParent != null)
                {
                    if (this == testParent)
                    {
                        throw new Exception("You cannot set a recursive IMessageHandler parent.");
                    }
                    testParent = testParent.Parent;
                }

                if (!IsValidParent(value))
                {
                    throw new Exception("Invalid parent.");
                }

                if (HasParent())
                {
                    Parent.RemoveChild(this);
                    parent = null;
                }

                parent = value;

                if (HasParent())
                {
                    Parent.AddChild(this);
                }
            }
        }
        public bool HasParent()
        {
            return Parent != null;
        }
        public virtual bool IsValidParent(MessageHandlerBase theParent)
        {
            return true;
        }
        public bool HasChild(MessageHandlerBase theChild)
        {
            return Children.Contains(theChild);
        }
        public bool HasChildren()
        {
            return Children.Count > 0;
        }
        public virtual bool OnMessage(MessageBase theMessage)
        {
            return false;
        }
        public bool HandleMessage(MessageBase theMessage)
        {
            if (OnMessage(theMessage))
            {
                return true;
            }
            else
            {
                if (HasParent())
                {
                    return Parent.HandleMessage(theMessage);
                }
                else
                {
                    return false;
                }
            }
        }
        public void Broadcast(MessageBase theMessage, bool reverseOrder)
        {
            List<MessageHandlerBase> childList = new List<MessageHandlerBase>(Children);
            if (reverseOrder) childList.Reverse();
            OnMessage(theMessage);
            foreach (var child in childList)
            {
                child.Broadcast(theMessage, reverseOrder);
            }
        }
        public bool HandleBroadcast(MessageBase theMessage, bool reverseOrder)
        {
            List<MessageHandlerBase> childList = new List<MessageHandlerBase>(Children);
            if (reverseOrder) childList.Reverse();
            if (!reverseOrder)
            {
                if (OnMessage(theMessage)) return true;
            }
            foreach (var child in childList)
            {
                if (child.HandleBroadcast(theMessage, reverseOrder))
                {
                    return true;
                }
            }
            if (reverseOrder)
            {
                return OnMessage(theMessage);
            }
            return false;
        }

    }
}
